/**
 * 基于XLSX的Excel数据导出组件
 * @author SPY
 * @date 2020/03/15
 */

import React from 'react';
import XLSX from 'xlsx';

/**
 * 导出组件
 * @param {array} sheets -- 格式：[{ headers: columns, data: dataSource, sheetName: "员工基本信息" }]
 * @param {string} fileName 
 */
const ExcelImport = (sheets, fileName = '下载excel文件') => {

    /**
     * 将数字下标转化为：A、B、C...
     * @param {number} index 
     */
    const getPostition = (index) => {
        let result = String.fromCharCode(65 + parseInt(index % 26));
        let value = index / 26;
        while (value >= 1) {
            result = String.fromCharCode(65 + parseInt(value % 26 - 1)) + result;
            value = parseInt(value / 26);
        }
        return result;
    }

    const getColWidth = (headers, dataArr) => {
        const allWch = [headers,].concat(dataArr).map(item => item.map(val => {
            let value = val.title || val.content || "";
            let length = 10;
            /*先判断是否为null/undefined*/
            if (value) {
                /*再判断是否为中文*/
                if (value.toString().charCodeAt(0) > 255) {
                    length = value.toString().length * 2;
                } else {
                    length = value.toString().length;
                }
            }
            return {
                'wpx': length < 40 ? length * 10 : 40 * 10, // wpx以像素为单位，规则：一个汉字占20像素，一个数字占10像素
                // 'wch': length < 40 ? length : 40, // wch表示以字符串为单位,但是目前好像不起作用
            };
        }))
        /*以第一行为初始值*/
        let colWidth = allWch[0];
        for (let i = 1; i < allWch.length; i++) {
            for (let j = 0; j < allWch[i].length; j++) {
                if (colWidth[j]['wpx'] < allWch[i][j]['wpx']) {
                    colWidth[j]['wpx'] = allWch[i][j]['wpx'];
                }
            }
        }
        return colWidth;
    }

    const sheetsArr = sheets.map(sheet => {
        const _headers = sheet.headers
            .map((item, i) => Object.assign({}, { key: item.key, title: item.title, position: getPostition(i) + 1 }))
            .reduce((prev, next) => Object.assign({}, prev, { [next.position]: { key: next.key, v: next.title } }), {});
        const dataArr = sheet.data
            .map((item, i) => sheet.headers.map((head, j) => {
                let content = ""
                if (head.render) {
                    content = head.render(item[head.dataIndex], item)
                } else {
                    content = item[head.dataIndex]
                }
                return { content, position: getPostition(j) + (i + 2) }
            }
            ));
        // 对刚才的结果进行降维处理（二维数组变成一维数组）
        const _data = dataArr.reduce((prev, next) => prev.concat(next))
            // 转换成 worksheet 需要的结构
            .reduce((prev, next) => Object.assign({}, prev, { [next.position]: { v: next.content } }), {});
        // 合并 headers 和 data
        const output = Object.assign({}, _headers, _data);
        // 获取所有单元格的位置
        const outputPos = Object.keys(output);
        // 计算出范围 ,["A1",..., "H2"]
        const ref = `${outputPos[0]}:${outputPos[outputPos.length - 1]}`;
        return Object.assign(
            { sheetName: sheet.sheetName },
            output,
            {
                '!ref': ref,
                '!cols': getColWidth(sheet.headers, dataArr),
            },
        )
    })
    const sheetNames = sheetsArr.map(sheet => sheet.sheetName);
    const wbSheets = sheetsArr.reduce((prev, next) =>
        Object.assign({}, prev, { [next.sheetName]: next }), {});
    // 构建 workbook 对象
    const wb = {
        SheetNames: sheetNames,
        Sheets: wbSheets,
    };
    // 导出 Excel
    XLSX.writeFile(wb, fileName + ".xlsx");
}

export default ExcelImport;